home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / ast_comp / cpp-kit.lha / c++kit / Scan.C < prev    next >
C/C++ Source or Header  |  1993-04-11  |  5KB  |  260 lines

  1. /* 9th April, 1993 Mayan Moudgill
  2.  * Basically is given a file. If asked it will try and scan one of the
  3.  * following tokens from the file.
  4.  *    strings:    "([^"\\\n]|(\.))*"
  5.  *    identifier: [A-Za-z_0-9]+
  6.  *    integer:    [-+]?[0-9]+
  7.  *    character:  .
  8.  * These returns a Token.
  9.  * It can also accept a mark, which returns a Mark, and a reject which
  10.  * when given a Mark, rolls back the state to the Mark, and starts matching
  11.  * from that point onwards. Also, for convenience it can rollback the
  12.  * last token. Also, it can match a character and a character-string.
  13.  * (these are equivalent to trying to scanning a character/string,
  14.  * and rolling back if the character/string does not exactly match the
  15.  * argument).
  16.  *
  17.  * The other facility that the function provides is that it keeps track
  18.  * of the number of lines read in.
  19.  *
  20.  * I can think of at least of two ways of implementing the tokenizing
  21.  * and rollback mechanisms: reading files, and mmap'ing them. This
  22.  * implementation uses mmap.
  23.  */
  24.  
  25. #include <sys/types.h>
  26. #include <sys/mman.h>
  27. #include <sys/fcntl.h>
  28. #include <sys/stat.h>
  29. #include <ctype.h>
  30.  
  31. #include "Scan.H"
  32.  
  33. Scan::Scan()
  34. :  _close(1)
  35. {
  36. }
  37.  
  38. Scan::Scan(char * name)
  39. {
  40.    strncpy(_name, name, 255);
  41.    _name[255] = 0;
  42.    _fd = open(name, O_RDONLY);
  43.    if( _fd < 0 ) {
  44.       cerr << "could not open " << name << " cause: " << errno << endl;
  45.       _close = 1;
  46.       return;
  47.    }
  48.  
  49. struct stat buf;
  50.    fstat( _fd, &buf);
  51.    _size =  buf.st_size;
  52.    _file = mmap(0, (int)_size, PROT_READ, MAP_SHARED, _fd, 0);
  53.    if( (int)_file == -1 ) {
  54.       cerr << "could not mmap " << name << " cause: " << errno << endl;
  55.       _close = 1;
  56.    }
  57.    else {
  58.       _close = 0;
  59.       _end = _file + _size;
  60.    }
  61.    if( _size == 0 ) {
  62.       _eof = 1;
  63.    }
  64.    else {
  65.       _eof = 0;
  66.    }
  67.    _oat = _at = _file;
  68.    _onl = _nl = 0;
  69. }
  70.  
  71. Scan::~Scan()
  72. {
  73.    if( !_close ) {
  74.       munmap( _file, (int)_size);
  75.       close( _fd);
  76.       _close = 1;
  77.    }
  78. }
  79.  
  80. int     Scan::_space()
  81. {
  82.  
  83.    if( _start() ) {
  84.       return 1;
  85.    }
  86.    while( isspace(_get())) {
  87.    };
  88.    _backup();
  89.    _wnl = _tnl;
  90.    _wat = _tat;
  91.    return _eof;
  92. }
  93.  
  94. int     Scan::number(Token& result)
  95. {
  96. int     in;
  97.  
  98.    if( _space() ) {
  99.       result = Token(0,0);
  100.       return 0;
  101.    }
  102.  
  103.    in = _get();
  104.    if( in == '-' || in == '+' ) {
  105.       in = _get();
  106.    }
  107.    if( !isdigit(in) ) {
  108.       return 0;
  109.    }
  110.    do {
  111.       in = _get();
  112.    } while( isdigit(in));
  113.    _backup();
  114.    result = Token(_wat, _tat);
  115.    _commit();
  116.    return 1;
  117. }
  118.  
  119. int     Scan::identifier(Token& result)
  120. {
  121. int     in;
  122.  
  123.    if( _space() ) {
  124.       result = Token(0,0);
  125.       return 0;
  126.    }
  127.  
  128.    in = _get();
  129.  
  130.    if( in != '_' && !isalpha(in) ) {
  131.       result = Token(0, 0);
  132.       return 0;
  133.    }
  134.  
  135.    do {
  136.       in = _get();
  137.    } while ( in == '_' || isdigit(in) || isalpha(in) );
  138.    _backup();
  139.  
  140.    result = Token(_wat, _tat);
  141.    _commit();
  142.    return 1;
  143. }
  144.  
  145. int     Scan::string(Token& result )
  146. {
  147. int     in;
  148.  
  149.    if( _space() ) {
  150.       result = Token(0,0);
  151.       return 0;
  152.    }
  153.  
  154.    in = _get();
  155.    if( in != '"' ) {
  156.       result = Token(0,0);
  157.       return 0;
  158.    }
  159.    do {
  160.       in = _get();
  161.       if( in == '\\' ) {
  162.      _get();
  163.      in = _get();
  164.       }
  165.    } while( in != '"' );
  166.  
  167.    result = Token(_wat, _tat);
  168.    _commit();
  169.    return 1;
  170. }
  171.  
  172. int    Scan::token(Token& result)
  173. {
  174. int    in;
  175.    if( _space() ) {
  176.       result = Token(0,0);
  177.       return 0;
  178.    }
  179.  
  180.    in = _get();
  181.    _backup();
  182.    if( in ==  '"') {
  183.       if( string(result) ) {
  184.      result = Token( result.string()+1, result.length() - 2);
  185.      return 1;
  186.       }
  187.       else {
  188.      return 0;
  189.       }
  190.    }
  191.    else {
  192.       return identifier(result);
  193.    }
  194. }
  195.  
  196. int     Scan::character(Token& result)
  197. {
  198.    if( _start() ) {
  199.       result = Token(0, 0);
  200.       return 0;
  201.    }
  202.    _get();
  203.    result = Token(_wat, 1);
  204.    _commit();
  205.    return 1;
  206. }
  207.  
  208. int     Scan::match(char c, Token& result)
  209. {
  210. int   in;
  211.  
  212.    if( _start() ) {
  213.       result = Token(0,0);
  214.       return 0;
  215.    }
  216.    in = _get();
  217.    if( in == c ) {
  218.       _commit();
  219.       result = Token(_wat, 1);
  220.       return 1;
  221.    }
  222.    else {
  223.       result = Token(0,0);
  224.       return 0;
  225.    }
  226. }
  227.  
  228. int     Scan::match(char * s, Token& result)
  229. {
  230. int   in;
  231.  
  232.    if( _space() ) {
  233.       result = Token(0,0);
  234.       return 0;
  235.    }
  236.  
  237.    while( *s != 0  ) {
  238.       in = _get();
  239.       if( in != *s ) {
  240.      break;
  241.       }
  242.       s++;
  243.    }
  244.  
  245.    if( *s == 0 ) {
  246.       _commit();
  247.       result = Token(_wat, _tat);
  248.       return 1;
  249.    }
  250.    else {
  251.       result = Token(0,0);
  252.       return 0;
  253.    }
  254. }
  255.  
  256. int      Scan::eof()
  257. {
  258.    return _close || _at == _end;
  259. }
  260.